﻿namespace HiMap.Carto
{
    using HiMap.Geometry;
    using System;

    internal class FeatureCursorClass : IFeatureCursor
    {
        private ClassClass _Class;
        private IQueryFilter _Filter;
        private int DataRecIndex = -1;
        private int RecCount;
        private int SearchCount;
        private int[] SearchIds;

        internal FeatureCursorClass(IFeatureClass Class, IQueryFilter Filter)
        {
            this._Class = (ClassClass) Class;
            this._Filter = Filter;
            if (HiMap.Carto.VC.KWG_FEATURELAYER_GET_GEOMETRY_COUNT(Class.InPtr) == 0)
            {
                return;
            }
            if (Filter == null)
            {
                this.SearchCount = HiMap.Carto.VC.KWG_FEATURELAYER_GET_GEOMETRY_COUNT(Class.InPtr);
                this.RecCount = this.SearchCount;
            }
            else if (Filter.Type == FilterType.QueryFilter)
            {
                if ((Filter.WhereClause == null) || (Filter.WhereClause.ToString() == ""))
                {
                    this.SearchCount = HiMap.Carto.VC.KWG_FEATURELAYER_GET_GEOMETRY_COUNT(Class.InPtr);
                    this.RecCount = this.SearchCount;
                }
                else
                {
                    this.SearchIds = new int[HiMap.Carto.VC.KWG_FEATURELAYER_GET_GEOMETRY_COUNT(Class.InPtr)];
                    HiMap.Carto.VC.KWG_FEATURELAYER_SEARCHBYSQL(Class.InPtr, Filter.WhereClause, ref this.SearchIds[0], ref this.SearchCount);
                }
            }
            else if (Filter.Type != FilterType.GroupFilter)
            {
                if (Filter.Type == FilterType.SpatialFilter)
                {
                    IPoint geometry;
                    ISpatialFilter filter = (ISpatialFilter) Filter;
                    switch (filter.Geometry.Type)
                    {
                        case GeometryType.NotGeometry:
                        case GeometryType.MultiPoint:
                        case GeometryType.Polyline:
                        case GeometryType.Envelope:
                            goto Label_043C;

                        case GeometryType.Point:
                        {
                            geometry = (IPoint) filter.Geometry;
                            HiMap.Carto.POINTD pt = new HiMap.Carto.POINTD();
                            pt.X = geometry.X;
                            pt.Y = geometry.Y;
                            if (filter.QType != QueryType.Pixel)
                            {
                                this.SearchIds = new int[HiMap.Carto.VC.KWG_FEATURELAYER_GET_GEOMETRY_COUNT(Class.InPtr)];
                                if (!HiMap.Carto.VC.KWG_FEATURELAYER_SEARCHBYPOINT(Class.InPtr, pt, filter.Buffer, filter.WhereClause, ref this.SearchIds[0], ref this.SearchCount))
                                {
                                    this.SearchCount = 0;
                                }
                            }
                            else
                            {
                                int num3 = HiMap.Carto.VC.KWG_LAYER_GET_MAP(Class.InPtr);
                                if (num3 != 0)
                                {
                                    HiMap.Carto.POINTD pointd2;
                                    pointd2.X = 0;
                                    pointd2.Y = 0;
                                    int num4 = HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(num3);
                                    if (HiMap.Carto.VC.KWG_DISPLAYCONDITION_PIXEL_TO_MAP(num4, (int) geometry.X, (int) geometry.Y, ref pointd2.X, ref pointd2.Y))
                                    {
                                        double scale = 0;
                                        HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_SCALE(num4, ref scale);
                                        this.SearchIds = new int[HiMap.Carto.VC.KWG_FEATURELAYER_GET_GEOMETRY_COUNT(Class.InPtr)];
                                        if (!HiMap.Carto.VC.KWG_FEATURELAYER_SEARCHBYPOINT(Class.InPtr, pointd2, filter.Buffer * scale, filter.WhereClause, ref this.SearchIds[0], ref this.SearchCount))
                                        {
                                            this.SearchCount = 0;
                                        }
                                    }
                                }
                            }
                            goto Label_043C;
                        }
                        case GeometryType.Polygon:
                        {
                            IPolygon polygon = (IPolygon) filter.Geometry;
                            HiMap.Carto.POINTD[] pointdArray = new HiMap.Carto.POINTD[polygon.PointCount];
                            if (filter.QType != QueryType.Pixel)
                            {
                                for (int i = 0; i < polygon.PointCount; i++)
                                {
                                    pointdArray[i].X = polygon.GetPoint(i).X;
                                    pointdArray[i].Y = polygon.GetPoint(i).Y;
                                }
                            }
                            else
                            {
                                int num7 = HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(HiMap.Carto.VC.KWG_LAYER_GET_MAP(Class.InPtr));
                                for (int j = 0; j < polygon.PointCount; j++)
                                {
                                    geometry = polygon.GetPoint(j);
                                    HiMap.Carto.VC.KWG_DISPLAYCONDITION_PIXEL_TO_MAP(num7, (int) geometry.X, (int) geometry.Y, ref pointdArray[j].X, ref pointdArray[j].Y);
                                }
                            }
                            this.SearchIds = new int[HiMap.Carto.VC.KWG_FEATURELAYER_GET_GEOMETRY_COUNT(Class.InPtr)];
                            if (!HiMap.Carto.VC.KWG_FEATURELAYER_SEARCHBYPOLYGON(Class.InPtr, ref pointdArray[0], polygon.PointCount, filter.WhereClause, ref this.SearchIds[0], ref this.SearchCount))
                            {
                                this.SearchCount = 0;
                            }
                            goto Label_043C;
                        }
                    }
                }
            }
            else
            {
                int nField = -1;
                for (int k = 0; k < Class.Fields.FieldCount; k++)
                {
                    if (Class.Fields.GetField(k).Name.ToUpper() == Filter.WhereClause.ToString().ToUpper())
                    {
                        nField = k;
                        break;
                    }
                }
                if (nField < 0)
                {
                    return;
                }
                this.SearchIds = new int[HiMap.Carto.VC.KWG_FEATURELAYER_GET_GEOMETRY_COUNT(Class.InPtr)];
                HiMap.Carto.VC.KWG_FEATURELAYER_GET_GROUPIDLIST(Class.InPtr, nField, ref this.SearchIds[0], ref this.SearchCount);
            }
        Label_043C:
            this.DataRecIndex = this.SearchCount - 1;
        }

        void IFeatureCursor.Flush()
        {
            this.DataRecIndex = this.SearchCount - 1;
        }

        IFeature IFeatureCursor.Next()
        {
            IFeature feature = null;
            if (this.DataRecIndex >= 0)
            {
                int dataIndex = -1;
                if (this.RecCount > 0)
                {
                    dataIndex = this.DataRecIndex;
                }
                else
                {
                    dataIndex = this.SearchIds[this.DataRecIndex];
                }
                feature = new FeatureClass((IFeatureClass) this._Class, dataIndex);
                this.DataRecIndex--;
            }
            return feature;
        }
    }
}

